package server;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

//check that /bin/sh exists..

public class IPTablesComm {

	static String shell = "/bin/sh";
	static String shellOpt = "-c";
	static final String iptableTable = "mangle";
	static final String iptablesFile = "/sbin/iptables"; 

	static private void run(String command) throws FirewallException
	{
		try {
			String errorMsg = "";
			String[] cmd = {shell, shellOpt, command};
			System.out.println("Running: " + command);
			Process proc = Runtime.getRuntime().exec(cmd);
			BufferedReader input = new BufferedReader(new InputStreamReader(proc.getInputStream()));
			BufferedReader error = new BufferedReader(new InputStreamReader(proc.getErrorStream()));
			String line;
			while ((line = input.readLine()) != null)
			{
				System.out.println(line);
			}
			while ((line = error.readLine()) != null)
			{
				errorMsg += line + "\n";
				System.out.println(line);
			}
			input.close();
			int retval;
			try {
				retval = proc.waitFor();
				System.out.println("Return value was: " + retval);
				if (retval != 0)
					throw new FirewallException(errorMsg);
			} catch (InterruptedException e) {
			}
		} catch (IOException e) {
			throw new FirewallException();
		}
	}

	static void flush() throws FirewallException {
		// flush default allow/accept is allow?
		IPTablesComm.run(iptablesFile + " -t " + iptableTable + " -F");
	}

	//should i take the rule index ?
	static void add(RulesTableType dir, Rule rule, boolean log, String regexp) throws FirewallException {
		String Direction;
		if (dir == RulesTableType.IN)
			Direction = "INPUT";
		else
			Direction = "OUTPUT";
		if (rule.type == Rule.typeOpt.CONTEXT)
		{
			IPTablesComm.run(iptablesFile + " -t " + iptableTable + " -I " + Direction + " " + rule.index + " -m ipcontext --ipcontext_port " + rule.port + " --ipcontext_protocol " + rule.protocol + ((dir == RulesTableType.IN) ? " --ipcontext_dir 1 " : "") + (log ? " --ipcontext_log " : "") + " --ipcontext_regexp \"" + regexp + "\" -j " + ((rule.permission.toString().compareTo("ALLOW") == 0) ? "ACCEPT" : "DROP"));
		} else {
			String ruler = "";
			if (rule.iprange != null)
			{
				boolean range = rule.iprange.split("-").length == 2;
				String prefix = (dir == RulesTableType.IN) ? (range ? "-src-range" : "s") : (range ? "-dst-range" : "d");
				ruler += " -" + prefix + " " + rule.iprange + " ";
			}
			if (rule.port > 0)
			{
				String prefix = (dir == RulesTableType.IN) ? "-sport" : "-dport";
				ruler += " -" + prefix + " " + rule.port + " ";				
			}
//add logging
//			IPTablesComm.run(iptablesFile + " -t " + iptableTable + " -I " + Direction + " " + rule.index + " -p tcp " + ruler + (log ? " -j LOG --log-prefix \"OSLFW:\" " : "") + " -j " + ((rule.permission.toString().compareTo("ACCEPT") == 0) ? "ALLOW" : "DROP")); 
			IPTablesComm.run(iptablesFile + " -t " + iptableTable + " -I " + Direction + " " + rule.index + " -p tcp " + ruler + " -j " + ((rule.permission.toString().compareTo("ALLOW") == 0) ? "ACCEPT" : "DROP")); 
		}
	}

	static void remove(RulesTableType dir, int index) throws FirewallException {
		String Direction;
		if (dir == RulesTableType.IN)
			Direction = "INPUT";
		else
			Direction = "OUTPUT";
		IPTablesComm.run(iptablesFile + " -t " + iptableTable + " -D " + Direction + " " + index);
// add loging
//		IPTablesComm.run(iptablesFile + " -t " + iptableTable + " -D " + Direction + " " + index);
	}
}
